package com.stu.disruptor.service;

import com.lmax.disruptor.SleepingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.util.concurrent.Executors;

/**
 * 环形队列的工厂类
 */
public class DisruptorQueueFactory {
    public DisruptorQueueFactory() {
    }

    /**
     * 创建"点对点模式"的操作队列，即同一事件会被一组消费者其中之一消费
     * @param queueSize: 队列大小
     * @param isMoreProducer：是否支持多个生产者
     * @param consumers：多个消费者
     * @param <T>：实体类
     * @return：返回环形队列
     */
    public static <T> DisruptorQueue<T> getWorkPoolQueue(int queueSize, boolean isMoreProducer,
                                                         DisruptorConsumer<T>... consumers) {
        Disruptor<ObjectEvent<T>> _disruptor = new Disruptor(new ObjectEventFactory(),
                queueSize, Executors.defaultThreadFactory(),
                isMoreProducer ? ProducerType.MULTI : ProducerType.SINGLE,
                new SleepingWaitStrategy());
        _disruptor.handleEventsWithWorkerPool(consumers);
        return new DisruptorQueue(_disruptor);
    }

    /**
     * 创建"发布订阅模式"的操作队列，即同一事件会被多个消费者并行消费
     * @param queueSize：队列大小
     * @param isMoreProducer: 多个生产者
     * @param consumers：多个消费者
     * @param <T>：
     * @return
     */
    public static <T> DisruptorQueue<T> getHandleEventsQueue(int queueSize, boolean isMoreProducer,
                                                             DisruptorConsumer<T>... consumers) {
        Disruptor<ObjectEvent<T>> _disruptor = new Disruptor(new ObjectEventFactory(),
                queueSize, Executors.defaultThreadFactory(),
                isMoreProducer ? ProducerType.MULTI : ProducerType.SINGLE,
                new SleepingWaitStrategy());
        _disruptor.handleEventsWith(consumers);
        return new DisruptorQueue(_disruptor);
    }

    /**
     * 直接通过传入的 Disruptor 对象创建操作队列（如果消费者有依赖关系的话可以用此方法）
     * @param disruptor
     * @param <T>
     * @return：
     */
    public static <T> DisruptorQueue<T> getQueue(Disruptor<ObjectEvent<T>> disruptor) {
        return new DisruptorQueue(disruptor);
    }
}